package com.unalm.examensustitutorio.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.model.SelectItem;

public class Util {

	/**
	 * Metodo encargado de devolver el que mensaje solicitado del propertie.
	 * 
	 * @param bundleName
	 *            Nombre de la propiedad que se quiere obtener su mensaje.
	 * @param alternative
	 *            Sera el mensaje alternativo que se devolvera en caso no se
	 *            encuentre la propiedad buscada.
	 * @param ubicacion
	 *            Ubicacion del elemento propertie.
	 * @return
	 */
	public static String getMessageResourceString(String bundleName,
			String alternative, String ubicacion) {

		String text = null;

		Properties info = new Properties();
		try {
			info.load(Util.class.getResourceAsStream(ubicacion));
			text = info.getProperty(bundleName, alternative);

		} catch (IOException ex) {
			System.out.println(ex);
		}
		return text;
	}

	/**
	 * Retorna TRUE cuando el objeto es nulo. Caso contrario, retorna FALSE.
	 * 
	 * @param objeto
	 *            tipo Object
	 */
	public static boolean esNulo(Object objeto) {
		if (objeto == null)
			return true;
		return false;
	}

	/**
	 * Recibe un DATE y un formato de fecha (por ejemplo: dd/MM/yyyy) y retorna
	 * un String con la fecha formateada bajo ese patron
	 * 
	 * @param fecha
	 *            Date con la fecha a formatear, tipo Date
	 * @param pattern
	 *            patron del formato, tipo String
	 * @return fecha formateada, tipo String
	 */
	public static String formatearFecha(Date fecha, String pattern) {
		String fechaFormateada = null;
		if (fecha != null && pattern != null) {
			SimpleDateFormat df = new SimpleDateFormat(pattern);
			fechaFormateada = df.format(fecha);
		}
		return fechaFormateada;
	}

	/**
	 * Convierte un texto con fecha a un objeto Date
	 * 
	 * @param fecha
	 *            texto que se usa para crear la fecha, tipo String
	 * @param pattern
	 *            patron de conversion, tipo String
	 * @return fecha como Date, tipo Date
	 */
	public static Date convertirAFecha(String fecha, String pattern) {
		Date fechaResultado = null;
		try {
			if (!estaVacio(fecha) && !estaVacio(pattern)) {
				SimpleDateFormat df = new SimpleDateFormat(pattern);
				fechaResultado = df.parse(fecha);
			}
		} catch (Exception e) {
			System.err.println("ERROR: Ocurrio un error al convertir el "
					+ "texto " + fecha + " a Date");
			System.err.println(e);
			return null;
		}

		return fechaResultado;
	}

	/**
	 * Metodo encargado de dar la fecha Actual.
	 * @return <b>String</b> retorna Fecha Actual
	 */
	public static String fechaActual() {

		String fechaActual = null;
		Date date = new Date();
		SimpleDateFormat df = new SimpleDateFormat("dd/mm/yyyy hh:mm:ss");
		fechaActual = df.format(date);

		return fechaActual;

	}

	/**
	 * Recibe una cadena y retorna true si es que se trata de un valor numerico.
	 * Caso contrario, retorna false.
	 * 
	 * @param texto
	 *            string que se validara
	 * @return retorna TRUE cuando el numero es valido y FALSE en caso contrario
	 */
	public static boolean validarNumericoEntero(String texto) {
		boolean flgExito = true;
		try {
			Integer.parseInt(texto);
		} catch (Exception e) {
			flgExito = false;
		}
		return flgExito;
	}

	/**
	 * Valida un numero de RUC
	 * 
	 * @param texto
	 *            string que se validara
	 * @return retorna TRUE cuando el RUC es valido y FALSE en caso contrario
	 */
	public static boolean validarRUC(String texto) {
		boolean flgExito = true;
		Pattern myPattern = Pattern.compile("\\d{11}");
		Matcher myMatcher = myPattern.matcher(texto);
		if (!myMatcher.matches()) {
			flgExito = false;
		}
		return flgExito;
	}

	/**
	 * Valida un numero de DNI
	 * 
	 * @param texto
	 *            string que se validara
	 * @return retorna TRUE cuando el DNI es valido y FALSE en caso contrario
	 */
	public static boolean validarDNI(String texto) {
		boolean flgExito = true;
		Pattern myPattern = Pattern.compile("\\d{8}");
		Matcher myMatcher = myPattern.matcher(texto);
		if (!myMatcher.matches()) {
			flgExito = false;
		}
		return flgExito;
	}

	/**
	 * Return true cuando la fecha tiene el patron especificado
	 * 
	 * @param fecha
	 *            texto con fecha, tipo String
	 * @param pattern
	 *            patron para formatear fecha, tipo String
	 * @return TRUE en caso de formato correcto y FALSE en caso contrario
	 */
	public static boolean validarFecha(String fecha, String pattern) {
		boolean flgExito = true;
		Date date = convertirAFecha(fecha, pattern);
		if (date == null)
			flgExito = false;
		return flgExito;
	}

	/**
	 * Valida que la hora tenga el formato HH:mm (24 horas)
	 * 
	 * @param hora
	 *            texto de la fecha que sera validada, tipo String
	 * @return TRUE si pasa la validacion y FALSE en caso contrario
	 */
	public static boolean validarHora(String hora) {
		boolean flgExito = true;
		Pattern myPattern = Pattern
				.compile("^([0-1][0-9]|[2][0-3]):([0-5][0-9])$");
		Matcher myMatcher = myPattern.matcher(hora);
		if (!myMatcher.matches()) {
			flgExito = false;
		}
		return flgExito;
	}

	/**
	 * Retorna TRUE cuando el texto es diferente de NULL y diferente de cero (0,
	 * donde este valor representa a la opcion SELECCIONE o TODOS). Caso
	 * contrario retorna FALSE;
	 * 
	 * @param valor
	 *            texto que se evaluara, tipo String
	 * @return TRUE o FALSE dependiendo de la condicion cumplida
	 */
	public static boolean esValorDiferenteDeSeleccione(String valor) {
		if (!Util.estaVacio(valor)
				&& !valor.equals(Constantes.OPCION_SELECCIONAR))
			return true;

		return false;
	}

	/**
	 * Retorna FALSE cuando el texto es diferente de NULL y diferente de vacio.
	 * Caso contrario retorna TRUE;
	 * 
	 * @param valor
	 *            texto que se evaluara, tipo String
	 * @return TRUE o FALSE dependiendo de la condicion cumplida
	 */
	public static boolean estaVacio(String valor) {
		if (valor != null && !valor.equals("") && !valor.equals("null"))
			return false;
		return true;
	}

	/**
	 * Retorna TRUE cuando la lista parametro es vacia o nula. Caso contrario,
	 * retorn FALSE;
	 * 
	 * @param lista
	 *            lista que se evaluara, tipo ArrayList
	 * @return TRUE o FALSE dependiendo de la condicion cumplida
	 */
	public static boolean esListaVacia(List lista) {
		if (lista == null || lista.size() == 0)
			return true;
		return false;
	}

	/**
	 * Retorna TRUE cuando el valor parametro existe como id de alguno de los
	 * objetos de la lista. <b>Se recalca que el bean de la lista debe ser del
	 * tipo SelectItem</b>
	 * 
	 * @param lista
	 *            lista de busqueda, tipo ArrayList
	 * @param valor
	 *            valor que se busca dentro de la lista, tipo String
	 * @return TRUE o FALSE dependiendo de la condicion cumplida
	 */
	public static boolean existeValorEnSelectItems(List lista, String valor) {
		boolean existe = false;
		if (!esNulo(lista))
			for (int i = 0; i < lista.size(); i++) {
				SelectItem selectItem = (SelectItem) lista.get(i);
				if (selectItem.getValue().equals(valor)) {
					existe = true;
					break;
				}
			}
		return existe;
	}

	/**
	 * Retorna en label (de un selectItem) cuyo value coincide con el segundo
	 * parametro del metodo.
	 * 
	 * @param lista
	 *            lista de selectItems, tipo List
	 * @param valor
	 *            value del selectItem que se busca en la lista, tipo String
	 * @return label del selectItem, tipo String
	 */
	public static String obtenerLabelEnSelectItems(List lista, String valor) {
		String labelEncontrado = null;
		if (!esNulo(lista))
			for (int i = 0; i < lista.size(); i++) {
				SelectItem selectItem = (SelectItem) lista.get(i);
				if (selectItem.getValue().equals(valor)) {
					labelEncontrado = selectItem.getLabel();
					break;
				}
			}
		return labelEncontrado;
	}

	/**
	 * Retorna la posicion en la cual fue encontrada el id dentro de los objetos
	 * de la lista. <b>Se recalca que el bean de la lista debe ser del tipo
	 * SelectItem</b>
	 * 
	 * @param lista
	 *            lista de busqueda, tipo ArrayList
	 * @param valor
	 *            valor que se busca dentro de la lista, tipo String
	 * @return posicion en la lista del valor encontrado
	 */
	public static int obtenerPosicionEnListaSelectItems(List lista, String valor) {
		int posicion = -1;
		if (!esNulo(lista))
			for (int i = 0; i < lista.size(); i++) {
				SelectItem selectItem = (SelectItem) lista.get(i);
				if (selectItem.getValue().equals(valor)) {
					posicion = i;
					break;
				}
			}
		return posicion;
	}

	/**
	 * Retorna la hora actual del sistema segun el formato especificado
	 * 
	 * @param pattern
	 *            patro de fecha, por ejemplo: HH:mm:ss, tipo String
	 * @return hora formateada, tipo String
	 */
	public static String obtenerHoraActual(String pattern) {
		Date fechaActual = new Date();
		SimpleDateFormat df = new SimpleDateFormat(pattern);
		return df.format(fechaActual);
	}

	/**
	 * Retorna el valor del objecto como tipo String en caso que esta no sea
	 * nulo. Caso contario, retornara nulo.
	 * 
	 * @param objeto
	 *            objeto que se evaluara, tipo Object
	 * @return String lleno o null segun cumpla condicion, tipo String
	 */
	public static String getStringFromObject(Object objeto) {
		String valor = null;
		if (esNulo(objeto))
			return null;
		else
			valor = String.valueOf(objeto);
		return valor;
	}

	/**
	 * Convierte un vector de strings en una ArrayList de strings
	 * 
	 * @param vector
	 *            vector de strings, tipo String[]
	 * @return lista de strings, tipo ArrayList
	 */
	public static List convertirVectorStringAListaString(String[] vector) {
		List lista = null;
		if (vector != null) {
			lista = new ArrayList();
			for (int i = 0; i < vector.length; i++) {
				String valor = vector[i];
				lista.add(valor);
			}
		}
		return lista;
	}

	/**
	 * Convierte una lista de strings en un vector de strings
	 * 
	 * @param lista
	 *            lista de strings, tipo ArrayList
	 * @return vector de strings, tipo String[]
	 */
	public static String[] convertirListaStringAVectorString(List lista) {
		String[] vector = null;
		if (!esListaVacia(lista)) {
			vector = new String[lista.size()];
			for (int i = 0; i < lista.size(); i++) {
				String valor = (String) lista.get(i);
				vector[i] = valor;
			}
		}
		return vector;
	}

	public static byte[] getBytesFromFile(File file) throws Exception {

		InputStream is = new FileInputStream(file);
		System.out.println("\nDEBUG: FileInputStream is " + file);

		// Get the size of the file
		long length = file.length();
		System.out.println("DEBUG: Length of " + file + " is " + length + "\n");

		/*
		 * You cannot create an array using a long type. It needs to be an int
		 * type. Before converting to an int type, check to ensure that file is
		 * not loarger than Integer.MAX_VALUE;
		 */
		if (length > Integer.MAX_VALUE) {
			System.out.println("File is too large to process");
			return null;
		}

		// Create the byte array to hold the data
		byte[] bytes = new byte[(int) length];

		// Read in the bytes
		int offset = 0;
		int numRead = 0;
		while ((offset < bytes.length)
				&& ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {

			offset += numRead;

		}

		// Ensure all the bytes have been read in
		if (offset < bytes.length) {
			throw new IOException("Could not completely read file "
					+ file.getName());
		}

		is.close();
		return bytes;

	}

	/**
	 * Agrega N dias a la fecha enviada como parametro. Por ejemplo: Si se envia
	 * un 22/07/2011 y 3 dias, la nueva fecha sera 25/07/2011
	 * 
	 * @param fecha
	 *            date a la que se agregaran los dias, tipo Date
	 * @param nroDias
	 *            nro de dias que se sumaran, tipo Integer
	 */
	public static Date agregarDiasAFecha(Date fecha, int nroDias) {
		if (fecha != null) {
			System.out.println("> Fecha inicial : " + fecha);
			Calendar gcCalendar = new GregorianCalendar();
			gcCalendar.setTime(fecha);
			gcCalendar.add(Calendar.DATE, nroDias);
			System.out.println("> Fecha final: " + gcCalendar.getTime());
			fecha = gcCalendar.getTime();
		}
		return fecha;
	}

	/**
	 * regresa la cadena especificada en tipo Date, null si no es posible
	 * 
	 * @param correo
	 *            ej. "a@com.pe"
	 * @return boolean
	 */
	public static boolean validarCorreo(String correo) {

		Pattern pat = null;
		Matcher mat = null;

		pat = Pattern
				.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$");
		mat = pat.matcher(correo);

		if (mat.find()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * regresa la cadena especificada en tipo Date, null si no es posible
	 * 
	 * @param cadena
	 *            22/06/1986
	 * 
	 * @return boolean
	 */
	public boolean validarFecha(String cadena) {

		Pattern pat = null;
		Matcher mat = null;

		pat = Pattern
				.compile("^(0?[1-9]|[12][0-9]|3[01])\\/(0?[1-9]|1[012])\\/[0-9]{4}$");
		mat = pat.matcher(cadena);

		if (mat.find()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * regresa la cadena especificada en tipo Date, null si no es posible
	 * 
	 * @param cadena
	 *            ej. "1980-06-01"
	 * @param formato
	 *            ej. "yyyy-mm-dd"
	 * @return Date
	 */
	public Date convertirCadenaFecha(String cadena, String formato)
			throws ParseException {

		Date date = null;

		SimpleDateFormat formateador = new SimpleDateFormat(formato);

		try {

			long ltime = formateador.parse(cadena).getTime();

			date = new Date(ltime);

		} catch (ParseException e) {

			e.printStackTrace();
		}

		return date;
	}

	/**
	 * regresa la cadena especificada en tipo Date, null si no es posible
	 * 
	 * @param date
	 *            ej. "1980-06-01"
	 * @param formato
	 *            ej. "yyyy-mm-dd"
	 * @return Date
	 */
	public String convertirFechaCadena(Date date, String formato)
			throws Exception {

		String cadena = null;

		SimpleDateFormat formateador = new SimpleDateFormat(formato);

		try {

			cadena = formateador.format(date);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return cadena;
	}

	/**
	 * Metodo encargado de ver si un texto tiene contenido numerico
	 * 
	 * @param texto
	 *            contenido del cual se analizara si tiene contenido numerico.
	 * @return <b>True</b> Si el texto no presenta caracteres numericos. <br>
	 *         <b>False</b> Si el texto presenta caracteres numericos.
	 */
	public static boolean validaTextoNoNumerico(String texto) {

		boolean valido = true;

		int numero = 0;

		for (int i = 0; i < texto.length(); i++) {

			try {
				numero = Integer.parseInt(texto.charAt(i) + "");

				return false;
			} catch (Exception e) {
				valido = true;
			}

		}

		return valido;

	}

	/**
	 * convierte una variable null a vacio
	 * 
	 * @param texto
	 *            ej. "null"
	 * @return cadena
	 */
	public static String nullToBlank(Object texto) {

		try {

			if (texto == null) {

				return "";
			}
			if (texto.toString().trim().equals("null")) {

				return "";
			}

			return texto.toString().trim();

		} catch (Exception e) {

			return "";
		}

	}

	public static void main(String[] args) {

		System.out.println(fechaActual());

	}
}
